package org.jiuling.xml.read;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jiuling.local.tools.verify.BooleanVerify;
import org.jiuling.xml.exception.XMLRuntimeException;

import java.io.StringReader;
import java.util.*;


/**
 * 用于Java的文档对象模型
 * @author 紫灵
 * @date 2024年01月27日 16时17分47秒
 */
public class DocumentObjectModelForJava {

    /**
     * 获取XML文件
     * @param xmlStr XML字符串
     * @return XML文件
     */
    private Document getDocument(String xmlStr){
        // 创建Reader对象
        SAXReader reader = new SAXReader();
        try {
            // 加载xml
            return reader.read(new StringReader(xmlStr));
        } catch (DocumentException e) {
            throw new XMLRuntimeException(e);
        }
    }

    /**
     * 获取属性
     * @param element 节点
     * @return 属性Map
     */
    private Map<String,Object> getAttribute(Element element){
        Map<String,Object> attributeMap = new HashMap<>();
        // 获取属性列表
        List<Attribute> attributeList = element.attributes();
        attributeList.forEach(attribute -> {
            // 封装属性到Map中
            attributeMap.put(attribute.getName(),attribute.getValue());
        });
        return attributeMap;
    }

    /**
     * 读取节点
     * @param element 节点
     * @return 节点Map
     */
    public Map<String,Object> readElement(Element element){
        // 获取节点属性
        Map<String, Object> elementMap = getAttribute(element);
        // 判断元素是否含有文字或者空元素
        if(BooleanVerify.isTrue(element.isTextOnly())){
            elementMap.put("value",element.getStringValue());
        }else {
            // 当元素内容不是文字或者是空元素时判断是否有内容,即是否有子节点
            if(BooleanVerify.isTrue(element.hasContent())){
                // 读取子节点
                Iterator iterator = element.elementIterator();
                // 遍历子节点
                while (iterator.hasNext()){
                    // 子节点
                    Element subElement = (Element) iterator.next();
                    // 获取子节点名称
                    String subElementName = subElement.getName();
                    String subElementNameList = subElementName+"List";
                    Map<String, Object> subElementMap = readElement(subElement);
                    // 判断名称列表是都存在
                    if (elementMap.containsKey(subElementNameList)){
                        List<Map<String,Object>> elementMapList = (List<Map<String, Object>>) elementMap.get(subElementNameList);
                        elementMapList.add(subElementMap);
                        // 判断名称是否存在
                    }else if(elementMap.containsKey(subElementName)){
                        List<Map<String,Object>> elementMapList = new ArrayList<>();
                        elementMapList.add((Map<String, Object>) elementMap.get(subElementName));
                        elementMapList.add(subElementMap);
                        elementMap.put(subElementNameList,elementMapList);
                        elementMap.remove(subElementName);
                    }else {
                        elementMap.put(subElementName,subElementMap);
                    }
                }
            }
        }
        return elementMap;
    }

    /**
     * 读取
     * @param xmlStr XML字符串
     * @return XMLMap对象
     */
    public Map<String, Object> read(String xmlStr){
        Document document = getDocument(xmlStr);
        // 获取根节点
        Element rootElement = document.getRootElement();
        return readElement(rootElement);
    }
}
